package editor.widgets;

import observer.ObservedString;
import observer.StringObserver;
import util.StringUtil;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import java.awt.*;
import java.awt.event.InputMethodEvent;

/**
 * This is a {@link javax.swing.JTextArea} that automatically updates the {@link ObservedString} that it manages,
 * so that the model is updated properly.
 *
 * FIXME: This doesn't support being updated from outside the widget (e.g. undos) like {@link ObservedStringField} does.
 * 
 * @author Neil Dickson
 */
public class ObservedStringArea extends JTextArea implements StringObserver, DocumentListener, AncestorListener {
	private ObservedString value;

	public ObservedStringArea(ObservedString value,int rows,int columns) {
		super(rows, columns);
		this.value = value;
		setText(value.toString(),false);
		value.addObserver(this);
		getDocument().addDocumentListener(this);
		addAncestorListener(this);
	}

	public void valueChanged(ObservedString s, String oldValue) {
		setText(s.toString(),false);
	}

	public void setText(String text,boolean updateString) {
		int prevNumRows = StringUtil.getLineCount(value.toString());
		int newNumRows = StringUtil.getLineCount(text);
		super.setText(text);
		if (updateString) {
			value.setValue(this,text);
		}
		if (prevNumRows!=newNumRows) {
			setSize(getPreferredSize());
		}
	}
	public void setText(String text) {
		setText(text,true);
	}

	public void inputMethodTextChanged(InputMethodEvent event) {
		int prevNumRows = StringUtil.getLineCount(value.toString());
		int newNumRows = StringUtil.getLineCount(getText());
		value.setValue(this,getText());
		if (prevNumRows!=newNumRows) {
			setSize(getPreferredSize());
		}
	}

	public void caretPositionChanged(InputMethodEvent event) {

	}

	public void setBackground(Color bg) {
		super.setBackground(bg);
		setOpaque(bg.getAlpha()==255);
	}

	public void insertUpdate(DocumentEvent e) {
		int prevNumRows = StringUtil.getLineCount(value.toString());
		int newNumRows = StringUtil.getLineCount(getText());
		value.setValue(this,getText());
		if (prevNumRows!=newNumRows) {
			setSize(getPreferredSize());
		}
	}

	public void removeUpdate(DocumentEvent e) {
		int prevNumRows = StringUtil.getLineCount(value.toString());
		int newNumRows = StringUtil.getLineCount(getText());
		value.setValue(this,getText());
		if (prevNumRows!=newNumRows) {
			setSize(getPreferredSize());
		}
	}

	public void changedUpdate(DocumentEvent e) {
		int prevNumRows = StringUtil.getLineCount(value.toString());
		int newNumRows = StringUtil.getLineCount(getText());
		value.setValue(this,getText());
		if (prevNumRows!=newNumRows) {
			setSize(getPreferredSize());
		}
	}

	public int getRowHeight() {
		return super.getRowHeight();
	}

	public void ancestorAdded(AncestorEvent event) {
		value.addObserver(this);
	}

	public void ancestorRemoved(AncestorEvent event) {
		value.removeObserver(this);
	}

	public void ancestorMoved(AncestorEvent event) {}
}
